/*
 * HTMLProxyEdit.java
 *
 * Created on July 3, 2001, 2:54 PM
 */

package edu.berkeley.guir.webquilt.proxy;

import java.io.*;
import java.util.*;
import com.arthurdo.parser.*;
import edu.berkeley.guir.webquilt.*;
import gnu.rex.*;

/**
 * WebQuilt class to edit HTML to redirect links, etc through the proxy.
 *
 * <P>
 * This software is distributed under the
 * <A HREF="http://guir.cs.berkeley.edu/projects/COPYRIGHT.txt">
 * Berkeley Software License</A>.
 *
 * <PRE>
 * Revisions:  - WebQuilt-v1.0-1.0.0, Feb 01 2001, jheer
 *               Created class
 *             - WebQuilt-v1.0-2.0.0, Mar 10 2001, jheer
 *               Updated for new frame handling, deployment level proxying,
 *               and use of WebQuiltLogEntry wrapper.
 *             - WebQuilt-v2.0.0-2.0.1, Jan 1 2002, kaow
 *               Made a subclass of ProxyEdit, added task box/watermark,
 *               expanded JavaScript proxying, fixed HTMLRefreshEditor bugs
 * </PRE>
 *
 * This class utilizes the HtmlStreamTokenizer package from Arthur Do Consulting.<BR>
 * This class utilizes the Rex package from GNU.<BR>
 *
 * @author  Jeffrey Heer (
 *          <A HREF="mailto:jheer@hkn.eecs.berkeley.edu">jheer@hkn.eecs.berkeley.edu</A>
 *          )
 * @author  Wayne Kao (
 *          <A HREF="mailto:kaow@cs.berkeley.edu">kaow@cs.berkeley.edu</A>
 *          )
 * @since   JDK 1.3
 * @version WebQuilt-v2.0.0-2.0.1, Dec 29 2001
 *
 */
public class HTMLProxyEdit extends ProxyEdit {

    // HTMLProxyEdit constants
    public static final String TAG_A      = "a";
    public static final String TAG_AREA   = "area";
    public static final String TAG_BODY   = "body";
    public static final String TAG_FORM   = "form";
    public static final String TAG_FRAME  = "frame";
    public static final String TAG_META   = "meta";
    public static final String TAG_LINK   = "link";

    // Regular expressions for scripts
    private RexArray rexes;



    /**
     * ProxyEdit constructor.
     * @param strSvr the insecure server + URI of the proxy
     * @param strSSvr the secure server + URI of the proxy
     */
    public HTMLProxyEdit(String server, String secureServer) {
	super(server, secureServer);
	rexes = new RexArray(generateStrRexes());
    }

    /**
     * Sets the debug flag. If debug is true, links will
     *  be inserted for viewing the logs while surfing
     *  and for submitting bug reports
     * @param debug the desired debugging flag value
     */
    public void setMode(int mode) {
	if ( mode == DEBUG_MODE ) { debug = true; }
	if ( debug ) {
	    registerEditor(new HTMLDebugBodyEditor(),   "body"  );
	}
//	else {
//	    registerEditor(new HTMLDeployBodyEditor(),  "body"  );
//	}
    } //

    /**
     * Toggles 'sync' debugging option. This method does
     *  nothing if this.debug = false.
     * @param sync the set sync value
     */
    public void setSync(boolean sync) {
	if ( !debug ) { return; }

	HTMLDebugBodyEditor e = (HTMLDebugBodyEditor)editors.get("body");
	e.setSync(sync);
    }



    /**
     * Takes an input stream and edits the document so that links are
     *  redirected to the proxy server. It outputs the edited HTML
     *  to the specified output stream.
     * @param istream the input stream
     * @param ostream the output stream to client
     */
    public void proxyCode(InputStream istream, OutputStream ostream) {
	try {

	    PrintStream         out = new PrintStream(ostream);
	    HtmlStreamTokenizer tok = new HtmlStreamTokenizer(new BufferedReader(new InputStreamReader(istream)));

	    tagBase = new HtmlTag();
	    tagBase.setTag("base"); tagBase.setParam(tagBase.P_HREF, entry.strBase);

	    int type;
            boolean bodyEndTagFound = false;
	    boolean headerJSOut = false;
	    while ( (type = tok.nextToken()) != HtmlStreamTokenizer.TT_EOF ) {
//		out.print(tok.getWhiteSpace());

		StringBuffer val = tok.getStringValue();

		// token is a comment, just print it out
		if ( type == HtmlStreamTokenizer.TT_COMMENT ) {
		    out.print("<!-- " + val + " -->");

		// token is text, just print it out
		} else if ( type == HtmlStreamTokenizer.TT_TEXT ) {
		    out.print(val);

		// token is a tag
		} else if ( type == HtmlStreamTokenizer.TT_TAG ) {
		    HtmlTag tag = new HtmlTag();
		    tok.parseTag(val, tag);

		    String strTag = tag.getTagString().toLowerCase();

		    // editable openning tag found
                    if ( !tag.isEndTag() && editors.containsKey(strTag) ) {
		    	// found body tag but head not encountered yet
			if ( !headFlag && tag.getTagType() == tag.T_BODY ) {
			    out.print("<HEAD>");
			    out.print(printHeader());
			    out.print(printHeaderJS());
			    out.print("</HEAD>");
			    headFlag = true;
			    headerJSOut = true;
			}
			HTMLAbstractEditor tagEdit = (HTMLAbstractEditor)editors.get(strTag);
			String    newTag  = tagEdit.editTag(tag);
			out.print(newTag);

		    // found HEAD tag, process it so the base is handled correctly
		    } else if ( !tag.isEndTag() && tag.getTagType() == tag.T_HEAD ) {
			out.print( "<" + val + ">" + proxyHead(tok) );
			headFlag = true;
			headerJSOut = true;

		    // found base tag, update our own
		    } else if ( !tag.isEndTag() && tag.getTagType() == tag.T_BASE ) {
			String strGlobalTarget, strNewBase;

			// check if there's a global target for links
			if ( ( strGlobalTarget = tag.getParam(tag.P_TARGET) ) != null ) {
			    entry.strTarget = strGlobalTarget;
			}

			// check if the base HREF has a different value, set final base tag
			if ( ( strNewBase = tag.getParam(tag.P_HREF) ) != null ) {
			    entry.strBase = strNewBase;
			    tagBase       = tag;
			} else {
			    tag.setParam(tag.P_HREF, entry.strBase);
			    tagBase = tag;
			}

		    // found SCRIPT tag
		    } else if ( !tag.isEndTag() && tag.getTagType() == tag.T_SCRIPT ) {
			// if JS tag not out yet, print it out
			if (!headerJSOut) {
				out.print(printHeaderJS());
				headerJSOut = true;
			}
			// run it through so it doesn't get screwed up
			out.print( "<" + val + ">" + proxyScript(tok) );

		    // found closing body tag
		    } else if ( tag.isEndTag() && tag.getTagType() == tag.T_BODY) {

			// print out header if *still* not printed
			if (!headFlag) {
				out.print(printHeader());
				headFlag = true;
			}

                        // write out the footer with the webquilt task ending links
                        out.print(printFooter());
                        out.print("<" + val + ">");
                        bodyEndTagFound = true;

		    // pass the tag along
                    } else {
			out.print("<" + val + ">");
		    }
		}
	    }
            if (bodyEndTagFound == false) {
		// print out header if *still* not printed
		out.print(printHeader());
		headFlag = true;

                out.print(printFooter());
            }
	    out.close();

	} catch ( Exception e ) {
	    System.err.println("Caught exception " + e);
	    e.printStackTrace();
	}
    } //


    /**
     * Parses the head of a HTML document, taking care to
     *  properly update the <BASE> tag so that the client
     *  requests images, etc from the the right server.
     * @param tok the HTML stream tokenizer
     * @return a string buffer full of proxied html
     */
    public StringBuffer proxyHead(HtmlStreamTokenizer tok)
                            throws IOException, HtmlException {

	StringBuffer buf = new StringBuffer();
        buf.append(printHeaderJS());

	int type;
	while ( (type = tok.nextToken()) != HtmlStreamTokenizer.TT_EOF ) {
//	    buf.append(tok.getWhiteSpace());

	    StringBuffer val = tok.getStringValue();

	    // token is a comment, just print it out
	    if ( type == HtmlStreamTokenizer.TT_COMMENT ) {
		buf.append("<!-- " + val + " -->");

	    // token is text, just print it out
	    } else if ( type == HtmlStreamTokenizer.TT_TEXT ) {
		buf.append(val);

	    // token is an HTML tag
	    } else if ( type == HtmlStreamTokenizer.TT_TAG ) {
		HtmlTag tag = new HtmlTag(); tok.parseTag(val, tag);

		String strTag = tag.getTagString().toLowerCase();
		if ( !tag.isEndTag() && editors.containsKey(strTag) ) {
		    // process tag
		    HTMLAbstractEditor tagEdit = (HTMLAbstractEditor)editors.get(strTag);
		    String    newTag  = tagEdit.editTag(tag);
		    buf.append(newTag);
		} else if ( !tag.isEndTag() && tag.getTagType() == tag.T_BASE ) {
		    // found base tag, update our own
		    String strGlobalTarget, strNewBase;

		    // check if there's a global target for links
		    if ( ( strGlobalTarget = tag.getParam(tag.P_TARGET) ) != null ) {
			entry.strTarget = strGlobalTarget;
		    }

		    // check if the base HREF has a different value, set final base tag
		    if ( ( strNewBase = tag.getParam(tag.P_HREF) ) != null ) {
			entry.strBase = strNewBase;
			tagBase       = tag;
		    } else {
			tag.setParam(tag.P_HREF, entry.strBase);
			tagBase = tag;
		    }
		} else if ( !tag.isEndTag() && tag.getTagType() == tag.T_SCRIPT ) {
		    // found SCRIPT tag, run it through so it doesn't get screwed up
		    buf.append( "<" + val + ">" + proxyScript(tok) );
		} else if ( tag.isEndTag() && tag.getTagType() == tag.T_HEAD) {
		    // found closing </HEAD> tag, let's finish up
		    // add extra WebQuilt content to head
                    buf.append(printHeader());
		    return buf.append("<" + val + ">");

		    //return buf.insert(0, "\n" + tagBase + "\n");
		} else {
		    // pass the tag along
		    buf.append("<" + val + ">");
		}
	    }
	}

	// never encountered closing </HEAD> tag
	return buf.insert(0, "\n" + printHeader() + "\n");
	//return buf.insert(0, "\n" + tagBase + "\n");

    } //

    /**
     * Parses a script section of the HTML document.
     *  Right now just passes the script text through
     *  unedited.
     * @param tok the HTML stream tokenizer
     * @return a string buffer full of proxied html
     */
    public StringBuffer proxyScript(HtmlStreamTokenizer tok)
                            throws IOException, HtmlException {

	StringBuffer buf = new StringBuffer();

	int type;

	/*
	  // random playing around with Rex
	  String strabc = "abc";
	  String strabc2 = "         abc";
	  try{
	  Rex r = Rex.build("abc");
System.out.println(r.match(strabc.toCharArray(), 0, strabc.length()));
System.out.println(r.match(strabc2.toCharArray(), 0, strabc2.length()));
	  }catch(Exception e){}
	 */

	while ( (type = tok.nextToken()) != HtmlStreamTokenizer.TT_EOF ) {
//	    buf.append(tok.getWhiteSpace());

	    StringBuffer val = tok.getStringValue();

	    // ## BEGIN ugly hack ####
	    // process annoying JS 'window.location.replace(...)' as well
	    // as 'window.location.href = "..."' redirects.
	    //  this fix is *UGLY* and should later be replaced with real JS parsing
	    String strValBlock = val.toString();
	    StringTokenizer strValTokenizer;
	    String strValToken = "";
	    /*
	    String[] t_str1 = {
		    "window.location.replace(\"",
		    "window.location.href = \"",
	    };
	    String[] t_str2 = {
		    "\")",
		    "\"",
	    };
	    */

	    RexResult rr;

	    strValTokenizer = new StringTokenizer(strValBlock, "\n", true);
	    strValBlock = "";
	    while (strValTokenizer.hasMoreTokens()) {
		strValToken = strValTokenizer.nextToken();

		if (strValToken.equals("\n")) {
			strValBlock += "\n";
			continue;
		}

	//	for ( int i = 0; i < t_str1.length; i++ ) {
		for ( int rexNum = 0; rexNum < rexes.length(); rexNum++ ) {

			// c_index and v_index indices delimit the matched URL in strValBlock
			int v_index = 0, c_index;



	//		while ( (c_index = strVal.indexOf(t_str1[i], v_index) ) != -1 ) {
			while ( (rr = rexes.getRex(rexNum).match(strValToken.toCharArray(),
								v_index,
								strValToken.length())) != null) {

	//		    c_index = c_index + t_str1[i].length();
	//		    v_index = strVal.indexOf(t_str2[i], c_index);
			    c_index = rr.offset(0) + rr.offset(1);
			    v_index = c_index + rr.length(1);
			    String strUrl = strValToken.substring(c_index, v_index);
			    //System.out.println('-' + strUrl + '-');

			    /*
			    replaced with client-side JavaScript code
			    // update URL --------
			    boolean secure = entry.secure;
			    if ( strUrl.startsWith("https://") ) {
				secure = true;
			    } else if ( WebQuiltLib.startsWithProtocol(strUrl) ) {
				secure = false;
			    }

			    strUrl = WebQuiltLib.generateAbsoluteUrl(entry.strBase, strUrl);
			    strUrl = URLEncoder.encode(strUrl);
			    strUrl = ( secure ? strSSvrUrl : strSvrUrl ) +
				"?" + PARAM_REPLACE + "=" + strUrl        +
				"&" + PARAM_TID     + "=" + entry.nextTID +
				"&" + PARAM_LINKID  + "=" + "-2";

			    if ( entry.parentID != -1 ) {
				strUrl = strUrl + "&" + PARAM_PARENTID + "=" + entry.parentID +
				    "&" + PARAM_FRAMEID  + "=" + entry.frameID;
			    }
			    strUrl = response.encodeURL(strUrl);
			    // end update ----------

			    val.delete(c_index, v_index);	// delete original URL
			    val.insert(c_index, strUrl);	// insert new URL
			    strVal = val.toString();
			    */
			    v_index = c_index + strUrl.length();

			    strValToken = strValToken.substring(0, c_index)
			    	+ " wq_proxy_url( "
				+ strUrl
				+ " ) "
			    	+ strValToken.substring(v_index,strValToken.length());

			} // end inner while

		    } // end for
		    strValBlock += strValToken + "\n";
	    } // end outer while
	    val = new StringBuffer(strValBlock);

	    // chop off final new line
	    val.deleteCharAt(val.length() - 1);

	    // ## END ugly hack ####

	    // token is a comment, just print it out
	    if ( type == HtmlStreamTokenizer.TT_COMMENT ) {
		buf.append("<!-- " + val + " -->");

	    // token is text, just print it out
	    } else if ( type == HtmlStreamTokenizer.TT_TEXT ) {
		buf.append(val);

	    // token is an HTML tag
	    } else if ( type == HtmlStreamTokenizer.TT_TAG ) {
		HtmlTag tag = new HtmlTag();
		tok.parseTag(val, tag);
		String strTag = tag.getTagString().toLowerCase();
		if ( tag.isEndTag() && tag.getTagType() == tag.T_SCRIPT) {
		    // found closing </SCRIPT> tag, let's finish up
		    buf.append("<" + val + ">");
		    return buf;
		} else {
		    // pass the tag along
		    buf.append("<" + val + ">");
		}
	    }
	}

	// never encountered closing </SCRIPT> tag
	return buf;

    } //

    /**
     * Prints regexes used for JavaScript matching
     * @return array of strings representing the regexes
     */
    public String[] generateStrRexes() {
	// some repeatedly used regexes
	String anything = ".*";
	String spaces = "\\S*";
	String dot = spaces + "\\." + spaces;
	String equal = spaces + "=" + spaces;
	String copen = "\\(";
	String cclose = "\\)";

	// places we might find URLs or JS code that evaluates to a URL
	// going to wrap our function around what's inside the matched subexpression
	String[] strRexes = {
	    // location.replace(url)
	    "location" + dot + "replace" + spaces + "(" + spaces + copen + "[^)]+" + cclose,

	    // location.href = url
	    "location" + dot + "href" + equal + copen + "[^;]+" + cclose,

	    // window.open(url) or window.open(url,blah,blah...)
	    "window" + dot + "open" + spaces + "(" + spaces + copen + "[^),]+" + cclose
	};
	for (int i = 0; i < strRexes.length; i++)
		strRexes[i] = anything + strRexes[i];
	return strRexes;
    }

    /**
     * Prints the WebQuilt Options at the bottom of the page.
     * @return a string with the footer to be printed
     */
    public String printHeader() {
	String styleCode = "";
	styleCode += "<style>\n";
	styleCode += "<!--\n";
	styleCode += ".webquilt_watermark { text-decoration: none; font-weight: normal; color: black; font-size: 11px; font-family: verdana, arial, helvetica }\n";
	styleCode += ".webquilt_watermark_link { text-decoration: none; font-weight: normal; color: blue; font-size: 11px; font-family: verdana, arial, helvetica }\n";
	styleCode += "-->\n";
	styleCode += "</style>\n\n";

	// tagBase: <base> tag which may have been rewritten by now
	// printHeaderJS(): JavaScript needed for proxying JavaScript
	String strBase = "\n\n" + tagBase + "\n\n\n";

	    // select the correct header and returns it
            if (entry.strTaskBox.equals("float"))
		return strBase + headerFloat(styleCode);

            if (entry.strTaskBox.equals("bottom"))
		return strBase + styleCode;

	    // if equals "off"
	    else
	        return strBase;
    }

    /**
     * Prints JavaScript to add to the header, including JavaScript proxying code
     * @return a string with the JavaScript header to be printed
     */
    public String printHeaderJS() {
	String header = "";

	header += "\n\n\n\n\n<SCRIPT LANGUAGE=JavaScript>\n";
	header += "<!--\n\n";
	header += "// Wayne Kao\n";
	header += "// Group for User Interface Research, UCB\n\n";

	// proxies a URL
	header += "function wq_proxy_url (strUrl) {\n";

	// these variables change on every page
	header += "	var strSSvrUrl = \"" + this.strSSvrUrl + "\";\n";
	header += "	var strSvrUrl =  \"" + this.strSvrUrl  + "\";\n";
	header += "	var strBaseUrl =  \"" + entry.strBase + "\";\n";
	header += "	var PARAM_REPLACE = \"" + PARAM_REPLACE + "\";\n";
	header += "	var PARAM_TID = \"" + PARAM_TID + "\";\n";
	header += "	var PARAM_LINKID = \"" + PARAM_LINKID + "\";\n";
	header += "	var TID = \"" + entry.nextTID + "\";\n";
	header += "	var secure;\n\n\n";

	header += "	if (  ( strUrl == null )                     ||\n";
	header += "	        strUrl.indexOf(strSSvrUrl) != -1     ||\n";
	header += "		strUrl.indexOf(strSvrUrl) != -1      ||\n";
	header += "	      ( strUrl.length == 0  )                ||\n";
	header += "	      ( strUrl.indexOf(\"mailto:\") != -1 )  ||\n";
	header += "	      ( strUrl.charAt(0) == '#' )            ||\n";
	header += "	      ( strUrl.indexOf(\"javascript:\") != -1) ) {\n";
	header += "	    return strUrl;\n";
	header += "	}\n\n";

	header += "	if ( strUrl.indexOf(\"https://\") != -1 ) { \n";
	header += "	    secure = true; \n";
	header += "	} else { // should check if starts with proper protocol?\n";
	header += "	    secure = false;\n";
	header += "	}\n\n";

	header += "	if ( strUrl.indexOf(\"http:\") != 1  && \n";
	header += "		 strUrl.indexOf(\"https:\") != 1 && \n";
	header += "		 strUrl.indexOf(\"ftp:\") != 1  && \n";
	header += "		 strUrl.indexOf(\"gopher:\") != 1 ) \n";
	header += "			strUrl = strBaseUrl + strUrl; \n\n";

	header += "	strUrl = ( secure ? strSSvrUrl : strSvrUrl ) + \n";
	header += "	    '?' + PARAM_REPLACE + '=' + strUrl        +\n";
	header += "	    '&' + PARAM_TID     + '=' + TID +\n";
	header += "	    '&' + PARAM_LINKID  + '=' + -2;\n\n";

	header += "	return strUrl;\n\n";

	header += "}\n\n";

	header += "//-->\n";
	header += "</SCRIPT>\n";

	return header;
    }


    /**
     * Prints code to add to the header, including watermark JavaScript
     * @return a string with the header to be printed
     */
    public String headerFloat(String styleCode) {

	String header = "";

	header += "\n\n\n\n\n<SCRIPT LANGUAGE=JavaScript>\n";
	header += "<!--\n\n";

	header += "/////////////////////////////////////////////////////\n";
	header += "// WebQuilt Watermark\n";
	header += "//\n";
	header += "// Wayne Kao\n";
	header += "// Group for User Interface Research, UCB\n";
	header += "//\n";
	header += "// Large portions of this code written by\n";
	header += "// Mark Morley (mark@islandnet.com)\n";
	header += "// Gregor (legreg@legreg.de)\n";
	header += "/////////////////////////////////////////////////////\n\n\n";

	header += "// Define some text\n\n\n";

	header += "var watermark_links_open = '<TABLE BORDER CELLPADDING=\"15\" style=\"float:right\" BGCOLOR=\"#000000\" ALIGN=RIGHT><TR><TD><nobr>';\n";
	header += "var watermark_links_close = '</nobr></TD></TR></TABLE>';\n\n\n\n";


	header += "var watermark_hidecommands = 'hidelayer(\\'webquilt_watermark_text\\');writetolayer(\\'webquilt_watermark_links\\',watermark_showlink);';\n\n";
	header += "var watermark_closelink = '<A HREF=\"javascript:hidelayer(\\'webquilt_watermark\\');hidelayer(\\'webquilt_watermark_text\\');\" onMouseOver=\"self.status=\\'Close WebQuilt box.\\';return true;\" onMouseOut=\"self.status=\\'\\'\"><span class=\"webquilt_watermark_link\">Close</span></A>';\n\n";
	header += "var watermark_hidelink = '<A HREF=\"javascript:' + watermark_hidecommands + '\" onMouseOver=\"self.status=\\'Hide WebQuilt box text.\\';return true;\" onMouseOut=\"self.status=\\'\\'\"><span class=\"webquilt_watermark_link\">Hide</span></A><br>' + watermark_closelink;\n\n";
	header += "var watermark_showlink = '<A HREF=\"javascript:showlayer(\\'webquilt_watermark_text\\');writetolayer(\\'webquilt_watermark_links\\',watermark_hidelink);\" onMouseOver=\"self.status=\\'Re-display WebQuilt box text.\\';return true;\" onMouseOut=\"self.status=\\'\\'\"><span class=\"webquilt_watermark_link\">Show</span></A><br>' + watermark_closelink;\n\n\n";


	header += "// Detect browser class\n";
	header += "var ie4 = (document.all) ? true : false;\n";
	header += "var ns4 = (document.layers) ? true : false;\n";
	header += "var ns6 = (document.getElementById && !document.all) ? true : false;\n\n\n";


	header += "function hidelayer(lay) {\n";
	header += "	if (ie4) {document.all[lay].style.visibility = \"hidden\";}\n";
	header += "	if (ns4) {document.layers[lay].visibility = \"hide\";}\n";
	header += "	if (ns6) {document.getElementById([lay]).style.display = \"none\";}\n";
	header += "}\n\n\n";

	header += "function showlayer(lay) {\n";
	header += "	if (ie4) {document.all[lay].style.visibility = \"visible\";}\n";
	header += "	if (ns4) {document.layers[lay].visibility = \"show\";}\n";
	header += "	if (ns6) {document.getElementById([lay]).style.display = \"block\";}\n";
	header += "}\n\n\n";

	header += "function writetolayer(lay,txt) {\n";
	header += "	if (ie4) {\n";
	header += "		document.all[lay].innerHTML = txt;\n";
	header += "	}\n";
	header += "	if (ns4) {\n";
	header += "		document[lay].document.write(txt);\n";
	header += "		document[lay].document.close();\n";
	header += "	}\n";
	header += "	if (ns6) {\n";
	header += "		over = document.getElementById([lay]);\n";
	header += "		range = document.createRange();\n";
	header += "		range.setStartBefore(over);\n";
	header += "		domfrag = range.createContextualFragment(txt);\n";
	header += "		while (over.hasChildNodes()) {\n";
	header += "			over.removeChild(over.lastChild);\n";
	header += "		}\n";
	header += "		over.appendChild(domfrag);\n";
	header += "	}\n";
	header += "}\n\n\n";

	header += "// Define the height and with of your image or html block here (in pixels).\n\n";

	header += "var height = 300;\n";
	header += "var width = 250;\n\n\n";

	header += "// You can set vpos to \"top\", \"center\", or \"bottom\".  Set hpos to \"left\",\n";
	header += "// \"center\", or \"right\".  This defines the location of your watermark on\n";
	header += "// the page.\n\n";

	header += "var vpos = \"bottom\";\n";
	header += "var hpos = \"right\";\n\n\n";

	header += "function watermark()\n";
	header += "{\n";
	header += "   if(ns4) {\n";

	header += "      n = window.pageYOffset;\n";
	header += "      if( vpos == \"bottom\" )\n";
	header += "         n += window.innerHeight - (height + 15);\n";
	header += "      else if( vpos == \"center\" )\n";
	header += "         n += window.innerHeight / 2 - (height + 15) / 2;\n";
	header += "      document.webquilt_watermark.top = n;\n";
	header += "      n = window.pageXOffset;\n";
	header += "      if( hpos == \"right\" )\n";
	header += "         n += window.innerWidth - (width + 15);\n";
	header += "      else if( hpos == \"center\" )\n";
	header += "         n += window.innerWidth / 2 - (width + 15) / 2;\n";
	header += "      document.webquilt_watermark.left = n;\n";
	header += "   }\n\n";

	header += "   else if(ie4) {\n";

	header += "      n = document.body.scrollTop;\n";
	header += "      if( vpos == \"bottom\" )\n";
	header += "         n += document.body.clientHeight - height;\n";
	header += "      else if( vpos == \"center\" )\n";
	header += "         n += document.body.clientHeight / 2 - height / 2;\n";
	header += "      document.all.webquilt_watermark.style.top = n;\n";
	header += "      n = document.body.scrollLeft;\n";
	header += "      if( hpos == \"right\" )\n";
	header += "         n += document.body.clientWidth - width;\n";
	header += "      else if( hpos == \"center\" )\n";
	header += "         n += document.body.clientWidth / 2 - width / 2;\n";
	header += "      document.all.webquilt_watermark.style.left = n;\n";
	header += "   }\n\n\n";

	header += "   // show watermark\n";
	header += "   setTimeout( \"watermark()\", 100 );\n";

	header += "}\n\n";

	header += "//-->\n";
	header += "</SCRIPT>\n";

	header += styleCode;

	header += "<!-- / WebQuilt Watermark -->\n";


	return header;

    }

    /**
     * Prints the WebQuilt Options at the bottom of the page.
     * @return a string with the footer to be printed
     */
    public String printFooter() {

            String strReset = (strSvrBase + WebQuiltConstants.PROXY_RESET);
//          String strTaskURL = (strSvrBase + "task/" + entry.strTaskID + ".htm");
            strReset = response.encodeURL(strReset);
	    String strTask = WebQuiltLib.getTaskDescription(entry.strTaskID);

            String strDone  = "<a href=\"" + strReset + "?exit=0\"\n" +
                            "onMouseOver=\"self.status='Click here if you have completed the task.';return true;\" \n" +
			    "onMouseOut=\"self.status=''\">" +
                            "<span class='webquilt_watermark_link'>Task Complete</span></a>\n";

            String strLeave = "<a href=\"" + strReset + "?exit=1\" " +
                            "onMouseOver=\"self.status='Stop trying this task and move on.';return true;\" \n" +
			    "onMouseOut=\"self.status=''\">" +
                            "<span class='webquilt_watermark_link'>Quit Task</span></a>\n";

//          String strTask = "<a href=\""  + strTaskURL + "\"" +
//	                    "onMouseOver=\"self.status='View the task description without ending task.';return true;\">\n" +
//	                    "View Task Description\n</a><br>\n";


	    // select the correct footer and returns it
            if (entry.strTaskBox.equals("float"))
		return footerFloat(strDone, strLeave, strTask);

	    else if (entry.strTaskBox.equals("bottom"))
		return footerBottom(strDone, strLeave, strTask);

	    // if equals "off"
	    else
	        return "";

    }

    /**
     * Prints the DHTML floating WebQuilt Options box at the bottom of the page.
     * @return a string with footer
     */
    public String footerFloat(String strDone, String strLeave, String strTask) {

	String footer = "";

	footer += "\n\n\n\n\n<!--\n";
	footer += "/////////////////////////////////////////////////////\n";
	footer += "// WebQuilt Watermark\n";
	footer += "// Wayne Kao\n";
	footer += "/////////////////////////////////////////////////////\n";
	footer += "-->\n\n\n";

	footer += "<p>\n";
	footer += "<div id='webquilt_watermark' style='position:fixed;bottom:2em;right:1em'>\n";
	footer += "<TABLE BORDER='0' bgcolor=\"#000000\"><TR><TD>\n\n\n";

	footer += "<div id='webquilt_watermark_text'>\n";
	footer += footerBottom(strDone, strLeave, strTask);
	footer += "</div>\n\n\n";

	footer += "<SCRIPT LANGUAGE=\"JavaScript\">\n";
	footer += "<!--\n";
	footer += "if (ie4 || ns4) {\n";
	footer += "	document.write(watermark_links_open);\n";
	footer += "	document.write('<div id=\"webquilt_watermark_links\" class=\"webquilt_watermark\">');\n";
	footer += "	if (ie4)\n";
	footer += "		document.write(watermark_hidelink);\n";
	footer += "	else if (ns4)\n";
	footer += "		document.write(watermark_closelink);\n";
	footer += "	document.write('</div>');\n";
	footer += "	document.write(watermark_links_close);\n";
	footer += "}\n";
	footer += "//-->\n";
	footer += "</SCRIPT>\n\n\n";


	footer += "</TD></TR></TABLE>\n";
	footer += "</div>\n\n\n";

	footer += "<SCRIPT LANGUAGE=\"JavaScript\">\n";
	footer += "<!--\n";
	footer += "// show watermark\n";
	footer += "watermark();\n\n\n";

	footer += "// minimize watermark\n";
	footer += "//setTimeout(watermark_hidecommands, 3000 );\n";
	footer += "//-->\n";
	footer += "</SCRIPT>\n";
	footer += "<!-- / WebQuilt Watermark -->\n";


	return footer;

    }

    /**
     * Prints the plain HTML WebQuilt Options box at the bottom of the page.
     * @return a string with footer
     */
    public String footerBottom(String strDone, String strLeave, String strTask) {

	String footer = "";
	footer += "<p><TABLE BORDER CELLPADDING='15'>\n";
	footer += "<TR><TD BGCOLOR='#FFFFFF'>\n";
	footer += "<DIV CLASS=webquilt_watermark>\n";
	footer += "<b>WebQuilt</b>\n";
	footer += "<p><b>Task Description:</b>\n";
	footer += "<br>" + strTask + "\n\n\n";

	footer += "<p><b>Options:</b>\n";
	footer += "<br>-&nbsp;" + strDone + "\n";
	footer += "<br>-&nbsp;" + strLeave + "\n";
	footer += "</DIV>\n";
	footer += "</TD></TR>\n";
	footer += "</TABLE>\n";
	return (footer);

    } //

} // of class

//==============================================================================

/*
Copyright (c) 2001 Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. All advertising materials mentioning features or use of this software
   must display the following acknowledgement:

      This product includes software developed by the Group for User
      Interface Research at the University of California at Berkeley.

4. The name of the University may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/


